#include "pthreadPool.h"
#define NUM 3

int exitPipe[2];//退出管道
void handler(int signum);//退出信号

/* 线程池 */
int main(int argc, char *argv[])
{
    // ./server 
    ARGS_CHECK(argc,1);

    //父线程管理异步终止
    pipe(exitPipe);
    if(fork()){
        close(exitPipe[0]);
        signal(SIGUSR1,handler);
        wait(NULL);
        printf("Parent is going to exit.\n");
        exit(0);
    }
    close(exitPipe[1]);

    //工人线程池初始化
    int workNum = NUM;
    threadPool_t threadPool;
    initThreadPool(&threadPool,workNum);
    makeWorker(&threadPool);

    //网络初始化
    int sockFd = initTcp();
    int epfd = epoll_create(1);
    epollAdd(epfd,sockFd);
    epollAdd(epfd,exitPipe[0]);

    initLocalFile();
    //创建客户队列并初始化
    clientQueue_t clientQueue;
    initClientQueue(&clientQueue);

    struct epoll_event readySet[3];
    while(1){
        //每0.1s醒来一次
        int readyNum = epoll_wait(epfd,readySet,3,100);
        for(int i = 0;i < readyNum; ++i){
            //有链接到来的消息就绪队列
            if(readySet[i].data.fd == sockFd){
                int netFd = accept(sockFd,NULL,NULL);
                printf("Client connect.netfd = %d\n",netFd);
                epollAdd(epfd,netFd);
            }
            //有退出消息到来的就绪队列
            else if(readySet[i].data.fd == exitPipe[0]){
                printf("【Master】: It's time to go.\n");
                pthread_mutex_lock(&threadPool.mutex);
                threadPool.flag = 1;
                pthread_cond_broadcast(&threadPool.cond);
                pthread_mutex_unlock(&threadPool.mutex);
                for(int j = 0;j < threadPool.tidArr.workerNum;++j){
                    pthread_join(threadPool.tidArr.pthreadTid[j],NULL);
                }
                printf("【Master】: Bye-bye.\n");
                exit(0);
            }
            else{
                //监听到客户端消息
                int netFd = readySet[i].data.fd;
                printf("netFd = %d\n",netFd);
                trainState_t trainState;
                bzero(&trainState,sizeof(trainState));
                int retRecv = recv(netFd,&trainState.length,sizeof(trainState.length),0);
                recvn(netFd,&trainState.state,sizeof(trainState.state));
                recvn(netFd,&trainState.preLength,sizeof(trainState.preLength));
                recvn(netFd,trainState.buf,trainState.length);
                printf("Length = %d ,State = %d,PreLength = %d,Buf = %s\n",
                       trainState.length,trainState.state,trainState.preLength,trainState.buf);

                if(retRecv == 0 || trainState.length == 0){
                    //客户端退出
                    char userName[256] = {0};
                    getUserName(userName,clientQueue.clientFd[netFd]);
                    printf("User %s leave!\n",userName);
                    delFd(netFd,&clientQueue);
                    //退出时候客户返回根目录
                    updateUserPwd(clientQueue.clientFd[netFd],"~/",0);
                    clientQueue.clientFd[netFd] = -1;
                    epollDel(epfd,netFd);
                    close(netFd);
                    break;
                }
                if(trainState.state == REGISTER){
                    registerUser(trainState,netFd);
                }
                else if(trainState.state == LOGIN){
                    int ret = login(trainState,netFd,&clientQueue);
                    if(ret == 0){
                        //登陆成功开始计时
                        addFd(netFd,&clientQueue);
                    }
                }
                else if(trainState.state == LS){
                    //收到客户端命令，重置时间
                    delFd(netFd,&clientQueue);
                    addFd(netFd,&clientQueue);
                    handleShortCmd(trainState,netFd,clientQueue.clientFd[netFd]);
                }
                else if(trainState.state == CD){
                    //收到客户端命令，重置时间
                    delFd(netFd,&clientQueue);
                    addFd(netFd,&clientQueue);
                    handleShortCmd(trainState,netFd,clientQueue.clientFd[netFd]);
                }
                else if(trainState.state == PWD){
                    //收到客户端命令，重置时间
                    delFd(netFd,&clientQueue);
                    addFd(netFd,&clientQueue);
                    handleShortCmd(trainState,netFd,clientQueue.clientFd[netFd]);
                }
                else if(trainState.state == REMOVE){
                    //收到客户端命令，重置时间
                    delFd(netFd,&clientQueue);
                    addFd(netFd,&clientQueue);
                    handleShortCmd(trainState,netFd,clientQueue.clientFd[netFd]);
                }
                else if(trainState.state == MKDIR){
                    //收到客户端命令，重置时间
                    delFd(netFd,&clientQueue);
                    addFd(netFd,&clientQueue);
                    handleShortCmd(trainState,netFd,clientQueue.clientFd[netFd]);
                }
                else if(trainState.state == PUTS){
                    //收到客户端命令，重置时间
                    delFd(netFd,&clientQueue);
                    addFd(netFd,&clientQueue);
                }
                else if(trainState.state == GETS){
                    //收到客户端命令，重置时间
                    delFd(netFd,&clientQueue);
                    addFd(netFd,&clientQueue);
                }
                else if(trainState.state == TOKEN){
                    //验证token值
                    int retToken = token(trainState,netFd);
                    if(retToken != -1){
                        //success
                        //收到客户端命令，重置时间
                        delFd(netFd,&clientQueue);
                        pthread_mutex_lock(&threadPool.mutex);
                        enQueue(&threadPool.taskQueue,retToken,netFd);
                        printf("Time to work\n");
                        pthread_cond_signal(&threadPool.cond);
                        pthread_mutex_unlock(&threadPool.mutex);
                    }
                }
            }
        }
    }
    return 0;
}

void handler(int signum){
    printf("signum = %d\n",signum);
    write(exitPipe[1],"1",1);
}
